/*
 * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: CC0-1.0
 */

#pragma once

#include <stdbool.h>
#include <stdint.h>
#include "esp_err.h"

typedef void* rotary_encoder_handle_t;

/**
 * @brief Rotary Encoder direction type
 *
 */
typedef enum
{
    ROTARY_ENCODER_DIRECTION_NOT_SET = 0,        ///< Direction not yet known (stationary since reset)
    ROTARY_ENCODER_DIRECTION_CLOCKWISE,
    ROTARY_ENCODER_DIRECTION_COUNTER_CLOCKWISE,
} rotary_encoder_direction_t;

/**
 * @brief Rotary Encoder event type
 *
 */
typedef struct
{
    rotary_encoder_direction_t direction;
} rotary_encoder_event_t;

typedef void (*rotary_encoder_event_cb)(const rotary_encoder_event_t* encoder_event, const void* user_context);

/**
 * @brief Rotary Encoder config
 *
 */
typedef struct
{
    uint8_t gpio_encoder_a;             /*!< Encoder Pin A */
    uint8_t gpio_encoder_b;             /*!< Encoder Pin B */
    rotary_encoder_event_cb event_callback;
    void* user_context;
} rotary_encoder_config_t;

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief Create a rotary encoder.
 *
 * @param[in] config pointer of knob configuration.
 * @param[out] encoder_handle_ptr A pointer to rotary encoder device handle.
 *
 * @return ESP_OK if successful otherwise an error occurred.
 */
esp_err_t rotary_encoder_create(const rotary_encoder_config_t* config, rotary_encoder_handle_t* encoder_handle_ptr);

/**
 * @brief Remove a rotary encoder.
 *
 * @param[in] encoder_handle pointer of rotary encoder device.
 *
 * @return ESP_OK if successful otherwise an error occurred.
 */
esp_err_t rotary_encoder_remove(const rotary_encoder_handle_t encoder_handle);

/**
 * @brief Register the knob event callback function.
 * 
 * @param[in] encoder_handle Initialized rotary encoder handle.
 * @param[in] event_cb Pointer to an allocated rotary_encoder_state_t struct that will be filled
 * @param[in] user_context Pointer to user supplied event context.
 * 
 * @return ESP_OK if successful otherwise an error occurred.
*/
esp_err_t rotary_encoder_set_cb(const rotary_encoder_handle_t encoder_handle, rotary_encoder_event_cb event_cb, const void* user_context);

#ifdef __cplusplus
}
#endif